
if ("undefined" == typeof (SettlersAuto)) {
    var SettlersAuto = {};
};

(function () {
     
    var Cc = Components.classes;
    var Ci = Components.interfaces;

    function Event() {
        this.eventHandlers = new Array();
    }

    Event.prototype.addHandler = function (eventHandler) {
        this.eventHandlers.push(eventHandler);
    }

    Event.prototype.execute = function (args) {
        for (var i = 0; i < this.eventHandlers.length; i++) {
            this.eventHandlers[i](args);
        }
    }

    SettlersAuto.Version = "0.1";
    SettlersAuto.onPageLoaded = new Event();
    SettlersAuto.DataReceiver = {};
    SettlersAuto.DataReceiver.onReceiveResponse = new Event();

    function getWindowForRequest(request) {
        if (request instanceof Components.interfaces.nsIRequest) {
            try {
                if (request.notificationCallbacks) {
                    return request.notificationCallbacks
                                  .getInterface(Components.interfaces.nsILoadContext)
                                  .associatedWindow;
                }
            } catch (e) { }
            try {
                if (request.loadGroup && request.loadGroup.notificationCallbacks) {
                    return request.loadGroup.notificationCallbacks
                                  .getInterface(Components.interfaces.nsILoadContext)
                                  .associatedWindow;
                }
            } catch (e) { }
        }
        return null;
    }

    // Helper function for XPCOM instanciation (from Firebug)
    function CCIN(cName, ifaceName) {
        return Cc[cName].createInstance(Ci[ifaceName]);
    }

    // Copy response listener implementation.
    function TracingListener(isRequest) {
        this.isRequest = isRequest;
        this.window = null;
        this.originalListener = null;
        this.receivedData = [];   // array for incoming data.
    }

    TracingListener.prototype =
    {
        onDataAvailable: function (request, context, inputStream, offset, count) {
            var binaryInputStream = CCIN("@mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
            var storageStream = CCIN("@mozilla.org/storagestream;1", "nsIStorageStream");
            var binaryOutputStream = CCIN("@mozilla.org/binaryoutputstream;1", "nsIBinaryOutputStream");

            binaryInputStream.setInputStream(inputStream);
            storageStream.init(8192, count, null);
            binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));

            // Copy received data as they come.
            var data = binaryInputStream.readBytes(count);
            this.receivedData.push(data);

            binaryOutputStream.writeBytes(data, count);

            this.originalListener.onDataAvailable(request, context,
                storageStream.newInputStream(0), offset, count);
        },

        onStartRequest: function (request, context) {
            this.originalListener.onStartRequest(request, context);
        },

        onStopRequest: function (request, context, statusCode) {
            // Get entire response
            var responseSource = this.receivedData.join('');
            this.originalListener.onStopRequest(request, context, statusCode);

            SettlersAuto.DataReceiver.onReceiveResponse.execute({
                url : request.name,
                statusCode : statusCode,
                data: responseSource,
                window: this.window
            });
        },

        QueryInterface: function (aIID) {
            if (aIID.equals(Ci.nsIStreamListener) ||
                aIID.equals(Ci.nsISupports)) {
                return this;
            }
            throw Components.results.NS_NOINTERFACE;
        }
    }

    var httpRequestObserver = {

        observe: function (aSubject, aTopic, aData) {
            if (aTopic == "http-on-examine-response") {
                var newListener = new TracingListener(false);
                aSubject.QueryInterface(Ci.nsITraceableChannel);
                newListener.originalListener = aSubject.setNewListener(newListener);
                newListener.window = getWindowForRequest(aSubject);
            }
        },

        QueryInterface: function (aIID) {
            if (aIID.equals(Ci.nsIObserver) ||
                aIID.equals(Ci.nsISupports)) {
                return this;
            }

            throw Components.results.NS_NOINTERFACE;
        }
    };

    var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
    observerService.addObserver(httpRequestObserver, "http-on-examine-response", false);


    function onPageLoad(aEvent) {
        var doc = aEvent.originalTarget; // doc is document that triggered the event
        var win = doc.defaultView; // win is the window for the doc
        // test desired conditions and do something
        // if (doc.nodeName == "#document") return; // only documents
        // if (win != win.top) return; //only top window.
        // if (win.frameElement) return; // skip iframes/frames
        SettlersAuto.onPageLoaded.execute(win);
    }

    window.addEventListener("load", function load(event) {
        window.removeEventListener("load", load, false); //remove listener, no longer needed
        if (gBrowser) gBrowser.addEventListener("DOMContentLoaded", onPageLoad, false);
    }, false);

    SettlersAuto.Log = function (message) {
        console.log(message);
    }

})();
